package com.spring.demo5.factory.config;

import com.spring.demo4.factory.advice.MyAdvice;
import com.spring.demo4.factory.advisor.MyAdvisor;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.AopConfigException;

/**
 * 这个接口中定义了操作Aop代理配置的各种方法（比如指定被代理的目标对象、添加通知、添加顾问等等）。
 * 所有由spring aop创建的代理对象默认都会实现这个接口。
 *
 * @author vhans
 */
public interface MyAdvised extends MyTargetClassAware {

    /**
     * 返回配置是否已冻结，被冻结之后，无法修改已创建好的代理对象中的通知
     */
    boolean isFrozen();

    /**
     * 是否对目标类直接创建代理，而不是对接口创建代理，通俗点讲：如果是通过cglib创建代理，此方法返回true，否则返回false
     */
    boolean isProxyTargetClass();

    /**
     * 获取配置中需要代理的接口列表
     */
    Class<?>[] getProxiedInterfaces();

    /**
     * 判断某个接口是否被代理
     */
    boolean isInterfaceProxied(Class<?> intf);

    /**
     * 设置被代理的目标源，创建代理的时候，通常需要传入被代理的对象，最终被代理的对象会被包装为TargetSource类型的
     */
    void setTargetSource(TargetSource targetSource);

    /**
     * 返回被代理的目标源
     */
    TargetSource getTargetSource();

    /**
     * 设置是否需要将代理暴露在ThreadLocal中，这样可以在线程中获取到被代理对象
     */
    void setExposeProxy(boolean exposeProxy);

    /**
     * 返回exposeProxy
     */
    boolean isExposeProxy();

    /**
     * 设置此代理配置是否经过预筛选，以便它只包含适用的顾问(匹配此代理的目标类)，默认设置是“false”。
     * 如果已经对advisor进行了预先筛选，则将其设置为“true”，这意味着在为代理调用构建实际的advisor链时可以跳过ClassFilter检查。
     */
    void setPreFiltered(boolean preFiltered);

    /**
     * 返回preFiltered
     */
    boolean isPreFiltered();

    /**
     * 返回此代理配置中应用的所有Advisor列表
     */
    MyAdvisor[] getAdvisors();

    /**
     * 添加一个Advisor
     */
    void addAdvisor(MyAdvisor advisor) throws AopConfigException;

    /**
     * 指定的位置添加一个Advisor
     */
    void addAdvisor(int pos, MyAdvisor advisor) throws AopConfigException;

    /**
     * 移除一个Advisor
     */
    boolean removeAdvisor(MyAdvisor advisor);

    /**
     * 移除指定位置的Advisor
     */
    void removeAdvisor(int index) throws AopConfigException;

    /**
     * 查找某个Advisor的位置
     */
    int indexOf(MyAdvisor advisor);

    /**
     * 将advisor列表中的a替换为b
     */
    boolean replaceAdvisor(MyAdvisor a, MyAdvisor b) throws AopConfigException;

    /**
     * 添加一个通知
     */
    void addAdvice(MyAdvice advice) throws AopConfigException;

    /**
     * 向指定的位置添加一个通知
     */
    void addAdvice(int pos, MyAdvice advice) throws AopConfigException;

    /**
     * 移除一个通知
     */
    boolean removeAdvice(MyAdvice advice);

    /**
     * 获取通知的位置
     */
    int indexOf(MyAdvice advice);

    /**
     * 将代理配置转换为字符串，这个方便排错和调试使用的
     */
    String toProxyConfigString();
}
